#!/usr/bin/python3
# -*- coding: utf-8 -*-

from inspect import isfunction, getsource


def reject_if(
        p,
        msg: str = None
):
    """ 检查指定的条件是否满足，如果条件满足则抛出错误。

    :param p: 待检查的条件。
    :param msg: 如果条件不满足则抛出的错误提示。
    """
    if isfunction(p):
        if bool(p()):
            if msg:
                raise ValueError(msg)
            else:
                raise ValueError(getsource(p.__code__).strip())
    else:
        raise ValueError(repr(p) + ' is not a function')


def reject_if_not(
        o,
        msg: str = None
) -> None:
    reject_if(lambda: not o, msg)


def reject_if_negative(
        o: (int, float,),
        msg: str = None
) -> None:
    reject_if(lambda: o < 0, msg)


def reject_if_non_positive(
        o: (int, float,),
        msg: str = None
) -> None:
    reject_if(lambda: o <= 0, msg)


def reject_if_null(
        o,
        msg: str = None
) -> None:
    """ 检查指定的参数是否是None，如果是None则抛出错误。

    :param o: 待检查的对象。
    :param msg: 如果条件不满足则抛出的错误提示。
    """
    reject_if(lambda: o is None, msg)


def reject_if_blank(
        s,
        msg: str = None
):
    """ 检查指定的参数是否只包含空白，如果只包含空白则抛出错误。

    :param s: 待检查的字符串。
    :param msg: 如果条件不满足则抛出的错误提示。
    """
    reject_if(lambda: not isinstance(s, str) or s.isspace(), msg)


def reject_if_not_type(
        o: type,
        *args,
        msg: str = None
):
    """检查指定的参数是否是指定的类型，如果不是指定的类型则抛出错误。

    :param o: 待检查的类型。
    :param args: 期望的类型。
    :param msg: 如果条件不满足则抛出的错误提示。
    """
    reject_if(lambda: not isinstance(o, (*args,)), msg)


def reject_if_out_of_range(
        o: (int, float,),
        min_: (int, float,) = None,
        max_: (int, float,) = None,
        msg: str = None
) -> None:
    from sys import maxsize
    if min_ is None:
        min_ = -maxsize - 1
    if max_ is None:
        max_ = maxsize

    reject_if(lambda: min_ <= o <= max_, msg)


def reject_if_not_callable(
        o,
        msg: str = None
):
    """ 检查指定的参数是否可以执行，如果不能执行则抛出错误。

    :param o: 待检查的参数。
    :param msg: 如果条件不满足则抛出的错误提示。
    """
    reject_if(lambda: not callable(o), msg)
